//---------------------------------------------------------------------
//  This file is part of the Background Motion solution.
// 
//  Copyright (C) Mindscape (TM).  All rights reserved.
//  http://www.mindscape.co.nz
// 
//  THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//---------------------------------------------------------------------

using System;

using Microsoft.Practices.EnterpriseLibrary.Validation;

using Mindscape.BackgroundMotion.Core.Validators;
using System.Data.Linq;
using System.Data.Linq.Mapping;

namespace Mindscape.BackgroundMotion.Model
{
  /// <summary>
  /// Represents a Comment which can be applied to a Contribution
  /// </summary>
  /// <remarks>
  /// Comments are used to allow users to express their view about a Contribution, we only allow known users to post comments in the system but all users can view comments
  /// </remarks>
  [Table(Name = "Comment")]
  public sealed class Comment : ModelObject
  {
    private int _id;
    private int _contributionId;
    private int _memberId;
    private string _subject;
    private string _message;
    private DateTime _postedOn;

    private EntityRef<Contribution> _contribution;
    private EntityRef<Member> _member;

    public Comment()
    {
      _contribution = default(EntityRef<Contribution>);
      _member = default(EntityRef<Member>);

      PostedOn = DateTime.Now;
    }

    /// <summary>
    /// The unique identifier of this instance
    /// </summary>
    [Column(Storage = "_id", IsPrimaryKey = true, IsDbGenerated = true)]
    public override int Id
    {
      get { return _id; }
      set
      {
        if (_id != value)
        {
          OnPropertyChanging("Id");
          _id = value;
          OnPropertyChanged("Id");
        }
      }
    }

    /// <summary>
    /// Gets or sets the <see ref="Contribution"/> id associated with this <see ref="Comment"/>
    /// </summary>
    [Column(Storage = "_contributionId")]
    public int ContributionId
    {
      get { return _contributionId; }
      set
      {
        if ((_contributionId != value))
        {
          OnPropertyChanging("ContributionId");
          _contributionId = value;
          OnPropertyChanged("ContributionId");
        }
      }
    }

    /// <summary>
    /// Gets or sets the <see ref="Member"/> id associated with this <see ref="Comment"/>
    /// </summary>
    [Column(Storage = "_memberId")]
    public int MemberId
    {
      get { return _memberId; }
      set
      {
        if ((_memberId != value))
        {
          OnPropertyChanging("MemberId");
          _memberId = value;
          OnPropertyChanged("MemberId");
        }
      }
    }

    /// <summary>
    /// The subject of this instance
    /// </summary>
    [RequireValidator("Subject", 128)]
    [Column(Storage = "_subject")]
    public string Subject
    {
      get { return _subject; }
      set
      {
        if ((_subject != value))
        {
          OnPropertyChanging("Subject");
          _subject = value;
          OnPropertyChanged("Subject");
        }
      }
    }

    /// <summary>
    /// The message of this instance
    /// </summary>
    [RequireValidator("Message", 1000)]
    [Column(Storage = "_message")]
    public string Message
    {
      get { return _message; }
      set
      {
        if ((_message != value))
        {
          OnPropertyChanging("Message");
          _message = value;
          OnPropertyChanged("Message");
        }
      }
    }

    /// <summary>
    /// The date on which this instance was posted to the system
    /// </summary>
    [RequireDateTimeValidator("PostedOn")]
    [Column(Storage = "_postedOn")]
    public DateTime PostedOn
    {
      get { return _postedOn; }
      set
      {
        if ((_postedOn != value))
        {
          OnPropertyChanging("PostedOn");
          _postedOn = value;
          OnPropertyChanged("PostedOn");
        }
      }
    }

    /// <summary>
    /// The <see ref="Contribution"/> associated with this instance
    /// </summary>
    [Association(Storage = "_contribution", ThisKey = "ContributionId", IsForeignKey = true)]
    public Contribution Contribution
    {
      get { return _contribution.Entity; }
      set
      {
        UpdateAssociation("Contribution", ref _contribution, value,
          (Contribution c) => c.Comments.Remove(this),
          (Contribution c) => c.Comments.Add(this));
      }
    }

    /// <summary>
      /// The <see ref="Member"/> associated with this instance
    /// </summary>
    [Association(Storage = "_member", ThisKey = "MemberId", IsForeignKey = true)]
    public Member Member
    {
      get { return _member.Entity; }
      set
      {
        UpdateAssociation("Member", ref _member, value,
          (Member c) => c.Comments.Remove(this),
          (Member c) => c.Comments.Add(this));
      }
    }

    /// <summary>
    /// Validates this instance for a correct state
    /// </summary>
    /// <remarks>
    /// This is called by the Enterprise Library Validation framework
    /// </remarks>
    /// <param name="results">A set of ValidationResults indicating validation issues with the current instance</param>
    protected override void Validate(ValidationResults results)
    {
      results.AddAllResults(Validation.ValidateFromAttributes(this));

      Require("Contribution", ContributionId, Contribution, results);
      Require("Member", MemberId, Member, results);
    }

    /// <summary>
    /// Gets the signature of this instance
    /// </summary>
    public string Signature
    {
      get { return String.Concat("Posted by ", Member.Username, " @ ", PostedOn.ToString("dd/MM/yyyy hh:mm")); }
    }
  }
}